package com.douqu.game.core.util;

import com.bean.core.buffer.ByteBuffer;
import com.bean.core.util.MD5Utils;
import com.bean.core.util.TimeUtils;
import com.douqu.game.core.config.FunctionConfig;
import com.douqu.game.core.config.TimeLimitedActivitiesConfig;
import com.douqu.game.core.config.activity.ActivityHallConfig;
import com.douqu.game.core.config.challenge.WorldBossConfig;
import com.douqu.game.core.config.common.CommonData;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.e.E_TimeDataType;
import com.douqu.game.core.e.E_TimeLimitActivityType;
import com.douqu.game.core.entity.GameObject;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.battle.BattleTemp;
import com.douqu.game.core.entity.common.TwoTuple;
import com.douqu.game.core.entity.ext.TaskInfo;
import com.douqu.game.core.factory.*;
import com.douqu.game.core.i.ICalculateRandomField;
import com.douqu.game.core.protobuf.SGCommonProto;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.io.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.channels.FileChannel;
import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by Administrator on 2016/11/9.
 */
public class CoreUtils {
    public static final int ONT_DAT = 86400000; //24 * 60 * 60 * 1000;

    public static final int ONT_HOUR = 3600000;// 60 * 60 * 1000;

    public static final int ONE_MINUTE = 60000;// 60 * 1000;

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";

    public static final String YYYYMMDD = "yyyyMMdd";

    public static final String YYYYMMDDHH = "yyyyMMddHH";
    /**
     * 手机号格式规范
     */
    public static final String PHONE_FORMAT = "^(13[0-9]|15[012356789]|17[0-9]|18[0-9]|14[57])[0-9]{8}$";
    /**
     * 充值测试账号
     */
    private static List<String> rechargeTestAccounts = new ArrayList<>();
    /**
     * 内部功能测账号
     */
    private static List<String> functionTestAccounts = new ArrayList<>();

    static {
        rechargeTestAccounts.add("YJ_DD72FEA8BCEE13F42018072406027044 ");//QA小米
        rechargeTestAccounts.add("YJ_F52F35C5A04A18767b563c72d4db6840d7cfd80e717fbd3dALI");//QA_UC
        rechargeTestAccounts.add("PHONE_18582456008");
        rechargeTestAccounts.add("PHONE_18601719211");
        rechargeTestAccounts.add("QUICK_18582456008");
        rechargeTestAccounts.add("QUICK_18601719211");
        rechargeTestAccounts.add("QUICK_726eca02c0e8d5e81ec14e6bb22f8fb5");
    }



    public static String createBattleId(String index1, String index2) {
        String a = index1.substring(Math.max(0, index1.length() - 4), index1.length());
        String b = index2.substring(Math.max(0, index2.length() - 4), index2.length());
        return a.toUpperCase() + CoreUtils.createUUID(4).toUpperCase() + b.toUpperCase();
    }

    public static String toString(CommonData[] datas) {
        StringBuilder result = new StringBuilder();
        for (CommonData commonData : datas) {
            result.append(commonData.id);
            result.append(ConstantFactory.SEMICOLON);
            result.append(commonData.value);
            result.append(ConstantFactory.DIVISION);
        }
        return result.length() > 0 ? result.substring(0, result.length() - 1) : "";
    }

    /**
     * 验证手机号格式
     *
     * @param phone
     * @return
     */
    public static boolean checkPhoneFormat(String phone) {
        Pattern pattern = Pattern.compile(PHONE_FORMAT);
        Matcher matcher = pattern.matcher(phone);
        return matcher.matches();
    }

    public static <T> T getMaxGameObject(List<T> list, Comparator comparator) {
        if (list == null || list.size() == 0)
            return null;

        if (list.size() == 1)
            return list.get(0);

        return (T) Collections.max(list, comparator);
    }

    public static <T> T getMinGameObject(List<T> list, Comparator comparator) {
        if (list == null || list.size() == 0)
            return null;

        if (list.size() == 1)
            return list.get(0);

        return (T) Collections.min(list, comparator);
    }

    public static boolean isNullOrEmpty(String text) {
        return text == null || text.equals("") || text.replaceAll(" ", "").length() == 0;
    }

    public static boolean isErrorValue(String value) {
        return "0".equals(value) || isNullOrEmpty(value);
    }

    public static <T> boolean arrayContainsValue(T[] arr, T obj) {
        boolean has = false;
        for (T t : arr) {
            if (t == obj) {
                has = true;
                break;
            }
        }
        return has;
    }

    /**
     * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {

        List<String> keys = new CopyOnWriteArrayList<String>(params.keySet());
        Collections.sort(keys);

        String prestr = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);

            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }

        return prestr;
    }

    /**
     * 获得内网IP
     *
     * @return 内网IP
     */
    public static String getIntranetIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获得外网IP
     *
     * @return 外网IP
     */
    public static String getInternetIp() {
        try {
            Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
            InetAddress ip = null;
            Enumeration<InetAddress> addrs;

            String INTRANET_IP = getIntranetIp();
            while (networks.hasMoreElements()) {
                addrs = networks.nextElement().getInetAddresses();
                while (addrs.hasMoreElements()) {
                    ip = addrs.nextElement();

                    if (ip != null
                            && ip instanceof Inet4Address
                            && ip.isSiteLocalAddress()
                            && !ip.getHostAddress().equals(INTRANET_IP)) {
                        return ip.getHostAddress();
                    }
                }
            }

            // 如果没有外网IP，就返回内网IP
            return INTRANET_IP;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String getChannelSuff(SGCommonProto.E_CHANNEL_TYPE channel) {
        String name = "";
        if (channel == null)
            name = SGCommonProto.E_CHANNEL_TYPE.CHANNEL_TYPE_UNKNOW.name();
        else
            name = channel.name();
        return name.substring(name.lastIndexOf("_") + 1);
    }

    /**
     * 根据平台生成账号
     *
     * @param account
     * @param channel
     * @return
     */
    public static String createAccount(String account, SGCommonProto.E_CHANNEL_TYPE channel) {
        account = account == null ? "" : account;
        account = account.replaceAll("_", "");
        return getChannelSuff(channel) + "_" + account;
    }

    /**
     * md5比较
     *
     * @param param    原始参数
     * @param md5Param 需要转md5再比较的参数
     * @return
     */
    public static boolean verifyMD5(String param, String md5Param) {
        return param.toUpperCase().equals(MD5Utils.encodeUppercase(md5Param));
    }

    public static String getRootPath() {
        return CoreUtils.class.getResource("/").getPath();
    }

    public static String getBasePath() {
        return System.getProperty("user.dir") + "/";
    }

    public static String createUUID(int num) {
        String[] strs = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
                "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
//        String time = System.currentTimeMillis()+"";
        StringBuffer sb = new StringBuffer();
        int r = 0;
        for (int i = 0; i < num; i++) {
            r = new Random().nextInt(strs.length);
            sb.append(strs[r]);
        }
//        sb.append(time.substring(time.length()-3));
        return sb.toString();
    }



    public static byte[] byteBufToBytes(ByteBuf byteBuf) {
        byte[] bytes = new byte[byteBuf.readableBytes()];
//        byteBuf.readBytes(bytes);
        byteBuf.getBytes(2, bytes);
        return bytes;
    }

    public static ByteBuffer toByteBuffer(ByteBuf byteBuf) {
        ByteBuffer buffer = new ByteBuffer();
        buffer.writeBytes(byteBufToBytes(byteBuf));
        return buffer;
    }

    // java 合并两个byte数组
    public static byte[] byteMerger(byte[] byte_1, byte[] byte_2) {
        byte[] byte_3 = new byte[byte_1.length + byte_2.length];
        System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);
        System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);
        return byte_3;
    }

    public static byte[] shortToByteArray(short n) {
        byte[] b = new byte[2];
        b[0] = (byte) (n & 0xff);
        b[1] = (byte) (n >> 8 & 0xff);
        return b;
    }

    public static String getFormatTime(String format, long time) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(time);
    }

    public static String getNowTimeStr() {
        return getFormatTime("yyyy-MM-dd HH:mm:ss", getNowTime());
    }

    public static boolean inDays(Date date, int days) {
        date = date == null ? new Date() : date;
        return Math.abs(date.getTime() - getNowTime()) < days * ONT_DAT;

    }

    /**
     * <p>Title: daysBetween1</p>
     * <p>Description: 计算两个日期天数</p>
     *
     * @param startTime
     * @param endTime
     * @return
     * @throws java.text.ParseException
     */
    public static int daysBetween(String startTime, String endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(CoreUtils.YYYY_MM_DD_HH_MM_SS);
        long end = sdf.parse(endTime).getTime();
        long start = sdf.parse(startTime).getTime();
        long between_days = (end - start) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * <p>Title: daysBetween1</p>
     * <p>Description: 计算两个日期天数</p>
     *
     * @param startTime
     * @param endTime
     * @return
     * @throws java.text.ParseException
     */
    public static int daysBetween(Date startTime, Date endTime) throws ParseException {
        long end = endTime.getTime() / 1000;
        long start = startTime.getTime() / 1000;
        long between_days = (end - start) / (1000 * 3600 * 24);
        return Integer.parseInt(String.valueOf(between_days));
    }

    public static String getDate(long date) {
        SimpleDateFormat sdf = new SimpleDateFormat(CoreUtils.YYYY_MM_DD_HH_MM_SS);
        Date dt = new Date(date);
        String time = sdf.format(dt);
        return time;
    }

    public static int getHour(){
        return Integer.parseInt(new SimpleDateFormat("H").format(new Date()));
    }

    public static int getWeek(){
        Calendar c = Calendar.getInstance();
        int dayForWeek = 0;
        if(c.get(Calendar.DAY_OF_WEEK) == 1){
            dayForWeek = 7;
        }else{
            dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }

    public static int getMinute(){
        return Integer.parseInt(new SimpleDateFormat("m").format(new Date()));
    }

    public static long getNowTime() {
        return System.currentTimeMillis();
    }

    /*
     * 从ByteBuf中获取信息 使用UTF-8编码返回
     */
    public static String getMessage(ByteBuf buf) {
//        System.out.println("总长度:"+buf.readableBytes());
//        int len = buf.readInt();
//        System.out.println("读取数据长度:"+len);
        byte[] con = new byte[buf.readableBytes()];
        buf.readBytes(con);
        try {
            return new String(con, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static ByteBuf getSendByteBuf(String message) throws UnsupportedEncodingException {

        byte[] req = message.getBytes("UTF-8");
        ByteBuf pingMessage = Unpooled.buffer();
//        pingMessage.writeInt(req.length);
        pingMessage.writeBytes(req);

        return pingMessage;
    }

    public static List<Integer> getRandomInteger(int num, int maxValue) {
        if (num == 0 || maxValue == 0 || num > maxValue) {
            return null;
        }
        List<Integer> list = new ArrayList<>();
        Random random = new Random();
        while (list.size() < num) {
            int product = random.nextInt(maxValue);
            if (list.contains(product)) {
                continue;
            } else {
                list.add(product);
            }
        }
        return list;
    }

    public static <T> List<T> arrayToList(T[] data) {
        List<T> list = new ArrayList<T>();
        if (data != null) {
            for (T t : data) {
                list.add(t);
            }
        }
        return list;
    }

    public static <T> void listToArray(List<T> list, T[] data) {
        if (list == null || data == null || list.size() != data.length) {
            return;
        }

        int size = list.size();
        for (int i = 0; i < size; i++) {
            data[i] = list.get(i);
        }
    }


//    //功能检测返回消息给客户端
//    public static void sendAlert(PlayerController playerController,int altarId){
//        FunctionConfig functionConfig = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, altarId);
//        if (playerController.getPlayer().getLv() < functionConfig.lv)
//            playerController.sendWarn(WordFactory.FUNCTION_NOT_OPEN));
//    }

    /**
     * 获取两个时间的间隔天数
     *
     * @param timeNow
     * @param timeAfter
     * @return
     */
    public static int getBetweenDay(long timeNow, long timeAfter) {
        if (timeAfter < timeNow) {
            return 0;
        }
        long between = (timeAfter - timeNow) / 1000;//除以1000是为了转换成秒
        int day = (int) (between / (24 * 3600));
        day = between % (24 * 3600) > 0 ? day + 1 : day;
        return day;
    }

    /**
     * 两个时间间隔几个24点算几天的特殊计算法
     *
     * @return
     */
    public static int getBetweenDay24(long timeNow, long timeAfter) {
        int days = 0;
        if (timeAfter < timeNow)
            return days;
        Date date = new Date(timeNow);
        Calendar calendar = Calendar.getInstance();
        //date.getYear() 获取的是1900到现在的年份
        calendar.set(date.getYear() + 1900, date.getMonth(), date.getDate(), 24, 00, 00);
        while (true) {
            if (calendar.getTime().getTime() < timeAfter) {
                days++;
            } else {
                return days;
            }
            calendar.add(Calendar.DATE, 1);
        }
    }

    /**
     * 检测功能是否开启
     * 返回NULL表示功能已开启
     * 返回其它字符串表示错误提示
     */
    public static String checkAltarFunctionOpen(int altarId, Player player) {
        int functionId = 0;
        switch (altarId) {
            case ConstantFactory.ALTAR_EXP_ALTAR_SYSTEM:
                functionId = FunctionFactory.UNLOCK_EXP_ALTAR_SYSTEM;
                break;
            case ConstantFactory.ALTAR_GOLD_ALTAR_SYSTEM:
                functionId = FunctionFactory.UNLOCK_GOLD_ALTAR_SYSTEM;
                break;
            case ConstantFactory.ALTAR_ACCESSORY_INTENSIFY_SYSTEM:
                functionId = FunctionFactory.UNLOCK_ACCESSORY_INTENSIFY_SYSTEM;
                break;
            case ConstantFactory.ALTAR_EQUIP_ALTAR_SYSTEM:
                functionId = FunctionFactory.UNLOCK_EQUIP_ALTAR_SYSTEM;
                break;
            case ConstantFactory.ALTAR_ACCESSORY_SCOURING_ALTAR_SYSTEM:
                functionId = FunctionFactory.UNLOCK_ACCESSORY_SCOURING_ALTAR_SYSTEM;
                break;
            case ConstantFactory.ALTAR_PROPERTY_WATER_ALTAR_SYSTEM:
                functionId = FunctionFactory.UNLOCK_PROPERTY_WATER_ALTAR_SYSTEM;
            default:
                break;
        }

        FunctionConfig functionConfig = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, functionId);
        if (functionConfig == null)
            return null;

        if (!CoreUtils.isFunctionUnLock(functionId, player)) {
            return MessageFormat.format(WordFactory.getWord(WordFactory.FUNCTION_NOT_OPEN), functionConfig.name);
        }
        return null;
    }

    public static String checkFunctionOpen(int functionId,Player player){
        FunctionConfig functionConfig = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, functionId);
        if (functionConfig == null)
            return null;

        if (!CoreUtils.isFunctionUnLock(functionId, player)) {
            return MessageFormat.format(WordFactory.getWord(WordFactory.FUNCTION_NOT_OPEN), functionConfig.name);
        }
        return null;
    }

    public static boolean isToday(long beforeTime, long afterTime) {
        return TimeUtils.getFormatTime(afterTime, new Object[]{"yyyyMMdd"}).
                equals(TimeUtils.getFormatTime(beforeTime, new Object[]{"yyyyMMdd"}));
    }

    public static boolean isTodayByOffset(long before, long after, int offsetHours) {
        long offset = offsetHours * 60 * 60 * 1000;
        return isToday(before - offset, after - offset);
    }

    public static boolean isSameWeek(long before, long after){
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date(before));
        int d = 0;
        if (cal.get(Calendar.DAY_OF_WEEK) == 1)
            d = -6;
        else
            d = 2 - cal.get(Calendar.DAY_OF_WEEK);

        cal.add(Calendar.DAY_OF_WEEK,d);
        int beforeMonth = cal.get(Calendar.MONTH);
        int beforeDay = cal.get(Calendar.DAY_OF_MONTH);

        cal.setTime(new Date(after));
        if (cal.get(Calendar.DAY_OF_WEEK) == 1)
            d = -6;
        else
            d = 2 - cal.get(Calendar.DAY_OF_WEEK);

        cal.add(Calendar.DAY_OF_WEEK,d);
        int afterMonth = cal.get(Calendar.MONTH);
        int afterDay = cal.get(Calendar.DAY_OF_MONTH);
        if (beforeMonth == afterMonth && beforeDay == afterDay){
            return true;
        }
        return  false;
    }

    /**
     * 获取下一个整数倍的数 1 ---》5
     *
     * @param mult
     * @param now
     * @return
     */
    public static int getNextMultNum(int mult, int now) {

        return (now / mult + 1) * mult;
    }

    /**
     * 拼接字符串
     *
     * @param strs
     * @return
     */
    public static String concat(Object... strs) {
        StringBuffer result = new StringBuffer();
        if (strs != null) {
            for (Object str : strs) {
                if (str != null)
                    result.append(str);
            }
        }
        return result.toString();
    }

    public static boolean isFunctionUnLock(int functionId, Player player) {
        FunctionConfig functionConfig = DataFactory.getInstance().getGameObject(DataFactory.FUNCTION_KEY, functionId);
        if (functionConfig != null) {
            if (player.getLv() < functionConfig.lv) {
                return false;
            } else if (functionConfig.taskId > 0 && !player.getExtInfo(TaskInfo.class).finishTasks.contains(functionConfig.taskId)) {
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * 获取当前时间到明天早上0:00的时间戳
     */
    public static long getNextDayStartOffsetMills(long currentTime) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 24);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
//        System.out.println(cal.get(Calendar.YEAR));
//        System.out.println(cal.get(Calendar.MONTH) + 1);
//        System.out.println(cal.get(Calendar.DATE));
//        System.out.println(cal.get(Calendar.HOUR));
//        System.out.println(cal.get(Calendar.MINUTE));
//        System.out.println(cal.get(Calendar.SECOND));
//        System.out.println(cal.getTimeInMillis());
//        System.out.println(System.currentTimeMillis());
        long offset = cal.getTimeInMillis() - currentTime;
//        offset = offset / 1000;
//        System.out.println(offset);
//        int hour = (int)offset / (60 * 60);
//        System.out.print(hour + "-" + ((offset - 3600 * hour) / 60));
        return offset;
    }

    public static int getStarNum(int i) {

        String s = Integer.toBinaryString(i);
        Pattern p = Pattern.compile("1");
        Matcher m = p.matcher(s);
        int sum = 0;
        while (m.find())
            sum++;
        return sum;
//        switch (i){
//            case 1:
//            case 2:
//            case 4:
//                return 1;
//            case 3:
//            case 5:
//            case 6:
//                return 2;
//            case 7:
//                return 3;
//        }
//        return 0;
    }

    public static boolean isFunctionTestAccount(String account) {
        return functionTestAccounts.contains(account);
    }

    public static boolean isRechargeTestAccount(String account) {
        return rechargeTestAccounts.contains(account);
    }


    public static <T> T getRandomObject(T[] t, int totalWeight, ICalculateRandomField<T> calculator) {
        if (t == null || t.length == 0 || calculator == null) {
            return null;
        }
        return getRandomObject(arrayToList(t), totalWeight, calculator);
    }

    public static <T> T getRandomObject(List<T> list, int totalWeight, ICalculateRandomField<T> calculator) {
        if (list == null || list.isEmpty() || calculator == null) {
            return null;
        }

        if (totalWeight <= 0) {
            totalWeight = 0;
            for (T t : list) {
                totalWeight += calculator.getFieldValue(t);
            }
        }

        int random = new Random().nextInt(totalWeight) + 1;
        int sum = 0;
        for (T t : list) {
            sum += calculator.getFieldValue(t);
            if (sum >= random) {
                return t;
            }
        }

        return list.get(list.size() - 1);
    }

    /**
     * <pre>
     * 判断date和当前日期是否在同一周内
     * 注:
     * Calendar类提供了一个获取日期在所属年份中是第几周的方法，对于上一年末的某一天
     * 和新年初的某一天在同一周内也一样可以处理，例如2012-12-31和2013-01-01虽然在
     * 不同的年份中，但是使用此方法依然判断二者属于同一周内
     * </pre>
     *
     * @param lastRecord
     * @return
     */
    public static boolean isSameWeekWithTodayByOffsetDay(long lastRecord) {

        // 0.先把Date类型的对象转换Calendar类型的对象
        Calendar todayCal = Calendar.getInstance();
        Calendar dateCal = Calendar.getInstance();

        todayCal.setTime(new Date(DataFactory.currentTime - ONT_DAT));
        dateCal.setTime(new Date(lastRecord - ONT_DAT));

        // 1.比较当前日期在年份中的周数是否相同
        if (todayCal.get(Calendar.WEEK_OF_YEAR) == dateCal.get(Calendar.WEEK_OF_YEAR)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取今天的首尾时间
     *
     * @return
     */
    public static TwoTuple<Long, Long> getInDayTime() {
        String formatTime = TimeUtils.getCurrentTime(TimeUtils.YYYY_MM_DD);
        Date date = TimeUtils.getDateByString(formatTime + " 00:00:00", TimeUtils.YYYY_MM_DD_HH_MM_SS);
        return new TwoTuple<>(date.getTime(), date.getTime() + ONT_DAT);
    }

    /**
     * 获取本周的首尾时间
     *
     * @return
     */
    public static TwoTuple<Long, Long> getInWeekTime() {
        TwoTuple<Long, Long> twoTuple = getInDayTime();
        int weekDay = TimeUtils.getWeekDay();
        twoTuple.setFirst(twoTuple.getFirst() - (weekDay - 1) * ONT_DAT);
        twoTuple.setSecond(twoTuple.getFirst() + ONT_DAT * 7);
        return twoTuple;
    }

    /**
     * 获取本周的首尾时间
     *
     * @return
     */
    public static TwoTuple<Long, Long> getTimeActivity() {
        TwoTuple<Long, Long> twoTuple = getInDayTime();
        twoTuple.setFirst(0l);
        twoTuple.setSecond(0l);
        List<TimeLimitedActivitiesConfig> configs = DataFactory.getInstance().getDataList(DataFactory.TIME_LIMIT_ACTIVITY_KEY);
        for (TimeLimitedActivitiesConfig config : configs) {
            if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode() && config.isTimeInForReceiver() && config.isServerIn(WorldInfoFactory.getInstance().getServerId())) {
                twoTuple.setFirst(TimeUtils.getDateByString(config.openTime[0].type + "", TimeUtils.YYYYMMDD).getTime());
                //结束时间要增加一天的毫秒数
                twoTuple.setSecond(TimeUtils.getDateByString(config.openTime[0].id + "", TimeUtils.YYYYMMDD).getTime() + 24 * 60 * 60 * 1000);
            }
        }
        return twoTuple;
    }

    /**
     * 这个方法查询的是上一条 对当前条不做处理
     * @return
     */
    public static TwoTuple<Long, Long> getNewTimeActivity(Calendar calendar) {
        TwoTuple<Long, Long> twoTuple = getInDayTime();
        twoTuple.setFirst(0l);
        twoTuple.setSecond(0l);
        List<TimeLimitedActivitiesConfig> configs = DataFactory.getInstance().getDataList(DataFactory.TIME_LIMIT_ACTIVITY_KEY);
        for (TimeLimitedActivitiesConfig config : configs) {
            if (config.type == E_TimeLimitActivityType.TOTAL_RECHARGE.getCode() && config.isLastDay(calendar) && config.isServerIn(WorldInfoFactory.getInstance().getServerId())) {
                twoTuple.setFirst(TimeUtils.getDateByString(config.openTime[0].type + "", TimeUtils.YYYYMMDD).getTime());
                //结束时间要增加一天的毫秒数
                twoTuple.setSecond(TimeUtils.getDateByString(config.openTime[0].id + "", TimeUtils.YYYYMMDD).getTime() + 24 * 60 * 60 * 1000 + 30 * 60 * 1000);
            }
        }
        return twoTuple;
    }

    /**
     * 获取本周的结束时间
     * @return
     */
    public static String getWeekEndTime(){
        TwoTuple<Long, Long> twoTuple = getInWeekTime();
        long distance = twoTuple.getSecond() - DataFactory.currentTime;
        int day = (int)distance / ONT_DAT;
        int hour = (int)(distance % ONT_DAT)/ONT_HOUR;
        int mins = (int)(distance % ONT_HOUR)/(1000 * 60);

        StringBuilder sb = new StringBuilder();
        if (day != 0){
            sb.append(day + "天");
        }

        if (hour != 0){
            sb.append(hour + "时");
        }

        sb.append(mins + "分");
        return sb.toString();
    }


    /**
     * 获取首末 时间
     *
     * @param start
     * @param end
     * @return
     */
    public static TwoTuple<Long, Long> getMinAndMaxTime(int start, int end) {
        long minTime = TimeUtils.getDateByString(start + "", TimeUtils.YYYYMMDD).getTime();
        long maxTime = TimeUtils.getDateByString(end + "", TimeUtils.YYYYMMDD).getTime() + CoreUtils.ONT_DAT;
        return new TwoTuple<>(minTime, maxTime);
    }

    public static long getNDaysAfter(long now, int n) {
        return TimeUtils.getDateByString(TimeUtils.getFormatTime(now, TimeUtils.YYYY_MM_DD) + " 00:00:00",
                TimeUtils.YYYY_MM_DD_HH_MM_SS).getTime() + (n + 1) * ONT_DAT;
    }

    public static String getGoodsName(GoodsData data) {
        int key = 0;
        if (data.type == SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_ASSETS_VALUE) {
            key = DataFactory.ASSET_KEY;
        } else if (data.type == SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_PROPS_VALUE) {
            key = DataFactory.PROP_KEY;
        } else if (data.type == SGCommonProto.E_GOODS_TYPE.GOODS_TYPE_CARDS_VALUE) {
            key = DataFactory.CARD_KEY;
        }

        GameObject object = DataFactory.getInstance().getGameObject(key, data.id);

        return object == null ? "" : object.name;
    }

    /**
     * fileChannel 复制文件
     */
    public static void copyFileUsingFileChannels(File source, File dest) {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                outputChannel.close();
                inputChannel.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }


    /**
     * 游戏内部使用的md5加密规则
     *
     * @param key
     * @return
     */
    public static String MD5Encode(String key) {
        String checkString = key + TimeUtils.getCurrentTime(TimeUtils.YYYYMMDD);
        return MD5Utils.encodeUppercase(checkString);
    }

    /**
     * 根据long 转 string 转 时间戳
     * @return
     */
    public static long longToTime(long value) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDDHH);
        return sdf.parse(Long.toString(value)).getTime();
    }

    /**
     * 根据时间戳 转 String 转 long
     * @param value
     * @return
     */
    public static long timeToLong(long value){
        SimpleDateFormat sdf = new SimpleDateFormat(YYYYMMDDHH);
        return Long.valueOf(sdf.format(new Date(value)));
    }

    /**
     * 获取当前是周几
     * @return
     */
    public static int getTodayWeek(long value){
        Date day = new Date(value);
        Calendar c = Calendar.getInstance();
        c.setTime(day);
        return c.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 得到已经结束的boss列表
     * @param hasKillList
     * @return
     */
    public static List<Integer> getEndBossList(List<Integer> hasKillList, BattleTemp bossInfo){
        List<WorldBossConfig> configList = DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_KEY);
        List<Integer> endBossList = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        for (WorldBossConfig config:configList){
            if (bossInfo != null && !CoreUtils.isNullOrEmpty(bossInfo.getIndexInfo()) && Integer.valueOf(bossInfo.getIndexInfo()) == config.id)
                continue;
            if (com.douqu.game.core.util.time.TimeUtils.isArriveTime(config.freshTime,calendar, E_TimeDataType.EVERYWEEK_TIME) &&
                    !hasKillList.contains(config.id))
                endBossList.add(config.id);
        }
        return endBossList;
    }

    /**
     * 根据星期几来取boss 如果今天没有boss取上一天的boss
     * @return
     */
    public static int getCurrentBossId(){
        List<WorldBossConfig> worldBossConfigList = DataFactory.getInstance().getDataList(DataFactory.WORLD_BOSS_KEY);
        /**
         * 如果当前天有boss取当前的boss
         * 如果没有取第一只boss
         */
        if (worldBossConfigList == null || worldBossConfigList.size() < 1){
            return 0;
        }
        int week = getWeek();
        int hour = getHour();
        int id = worldBossConfigList.get(0).id;
        List<WorldBossConfig> bossConfigList = new ArrayList<>();
        worldBossConfigList.forEach((config) ->{
            if (config.freshTime.timeArray[0] == week)
                bossConfigList.add(config);
        });
        if (bossConfigList.isEmpty())
            return id;
        //如果不仅一个boss
        bossConfigList.sort((o1,o2)-> o2.freshTime.timeArray[1] - o1.freshTime.timeArray[2]);
        id = bossConfigList.get(bossConfigList.size() - 1).id;
        for (WorldBossConfig config : bossConfigList) {
            if (hour > config.freshTime.timeArray[1]){
                id = config.id;
                break;
            }
        }
        return id;
    }

    public static long getBossBattleTime(long time){
        return time + 5 * ONE_MINUTE;
    }

    public static int getMaxPosition(int maxValue){
       String binary = binaryToDecimal(maxValue);
       return binary.length();
    }

    public static String binaryToDecimal(int n){
        String binary = "";
        boolean flag = false;
        for (int i = 31; i >= 0; i--){
           int a = n >>> i & 1;
           if (!flag){
               if (a == 1)
                   flag = true;
           }
           if (flag)
               binary += a;
        }
        return binary;
    }

//    public static int getGameNamePosition(){
//        int maxValue = 0;
//        for (SGCommonProto.E_GAME_NAME gameName:SGCommonProto.E_GAME_NAME.values()){
//            if (gameName.equals(SGCommonProto.E_GAME_NAME.UNRECOGNIZED))
//                continue;
//            if (gameName.getNumber() > maxValue)
//                maxValue = gameName.getNumber();
//        }
//        return getMaxPosition(maxValue);
//    }
//
//    public static int getServerTypePosition(){
//        int maxValue = 0;
//        for (SGCommonProto.E_SERVER_TYPE gameName:SGCommonProto.E_SERVER_TYPE.values()){
//            if (gameName.equals(SGCommonProto.E_SERVER_TYPE.UNRECOGNIZED))
//                continue;
//            if (gameName.getNumber() > maxValue)
//                maxValue = gameName.getNumber();
//        }
//        return getMaxPosition(maxValue);
//    }
//
//    public static int getPlatformPosition(){
//        int maxValue = 0;
//        for (SGCommonProto.E_PLATFORM_TYPE gameName:SGCommonProto.E_PLATFORM_TYPE.values()){
//            if (gameName.equals(SGCommonProto.E_PLATFORM_TYPE.UNRECOGNIZED))
//                continue;
//            if (gameName.getNumber() > maxValue)
//                maxValue = gameName.getNumber();
//        }
//        return getMaxPosition(maxValue);
//    }



    public static int getServerRuleId(int gameName,int serverType,int sMax,int platform,int pMax){
        /**
         * 1.首先知道platform的最大位数,serverType的最大位数,gameName的最大位数
         * 2.将gameName << sMax
         * 3.加入serverType
         * 4.将gameName << pMax
         * 5.加入platform
         */
        gameName = gameName << sMax;
        gameName += serverType;
        gameName = gameName << pMax;
        gameName += platform;
        return gameName;
    }

    public static int initRuleId(int gameName,int serverType,int platform){
        final int length = 8;
        int result = getServerRuleId(gameName,serverType,length,platform,length);
        return result;
    }

    public static int getPlatformPositionOld(){
        return 4;
    }
    public static int getServerTypePositionOld(){
        return 3;
    }
    public static int getGameNamePositionOld(){
        return 2;
    }
    public static int[] oldFormRuleId(int serverRuleId)
    {
        int gameName = serverRuleId >>> (getServerTypePositionOld() + getPlatformPositionOld());
        int serverType = serverRuleId << (32 - getServerTypePositionOld() - getPlatformPositionOld());
        serverType = serverType >>> (32 - getServerTypePositionOld());
        int platform = serverRuleId << (32 - getPlatformPositionOld()) >>> (32 - getPlatformPositionOld());
        return new int[]{gameName,serverType,platform};
    }

    public static int[] formRuleId(int serverRuleId)
    {
        final int length = 8;
        int gameName = serverRuleId >>> (length + length);
        int serverType = serverRuleId << (32 - length - length);
        serverType = serverType >>> (32 - length);
        int platform = serverRuleId << (32 - length) >>> (32 - length);
        return new int[]{gameName,serverType,platform};
    }

    /**
     * 验证这个用户所在平台是否可以使用此cdk
     * @param ruleId
     * @param platform
     * @return true 表示不能用 false 表示能用
     */
    public static boolean isTrueRule(Integer ruleId, Integer platform)
    {
        int[] arr = CoreUtils.formRuleId(ruleId);
        if (arr[2] == platform)
            return false;
        return true;
    }

    /**
     * 判断数组中是否存在某对象
     * @param value
     * @param arr
     * @return
     */
    public static boolean isContain(Object value,Object[] arr){
        AtomicBoolean result = new AtomicBoolean(false);
        Arrays.stream(arr).parallel().forEach((a)->{
            if (a.equals(value)){
                result.set(true);
                return;
            }
        });
        return result.get();
    }

    public static boolean isPlatform(int serverRuleId, SGCommonProto.E_PLATFORM_TYPE platformType)
    {
        try{
            int[] ary = formRuleId(serverRuleId);
            return ary[2] == platformType.getNumber();
        }catch (Exception e){
            LogUtils.errorException(e);
            return false;
        }
    }

    public static int getPlatformNumber(int serverRuleId)
    {
        try{
            int[] ary = formRuleId(serverRuleId);
            return ary[2];
        }catch (Exception e){
            LogUtils.errorException(e);
            return 0;
        }
    }

    /**
     * 根据时间遍历所有的活动 找到本周周历要显示的
     * @return
     */
    public static List<SGCommonProto.WeekCalendarColumn.Builder> initActivityWeekInfoList(){
        Map<SGCommonProto.E_WEEK, SGCommonProto.WeekCalendarColumn.Builder> map = new ConcurrentHashMap<>();
        List<ActivityHallConfig> configList = DataFactory.getInstance().getDataList(DataFactory.ACTIVITY_HALL);
        TwoTuple<Long,Long> twoTuple = getInWeekTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date(twoTuple.getFirst()));
        configList.forEach((config)->{
            //判断周历中是否显示该活动
            if (config.showWeek != 1)
                return;

            List<SGCommonProto.E_WEEK> weekList = com.douqu.game.core.util.time.TimeUtils.getArriveWeek(config.triggerTime,twoTuple);
            //获取触发时间是周几
            weekList.forEach((week)->{
                if (map.get(week) == null){
                    SGCommonProto.WeekCalendarColumn.Builder builder = SGCommonProto.WeekCalendarColumn.newBuilder();
                    builder.setWeek(week);
                    builder.addIdList(config.id);
                    map.put(week,builder);
                }else{
                    map.get(week).addIdList(config.id);
                }
            });
        });
        return new ArrayList<>(map.values());
    }



    /**
     * 遍历找到本日要显示的
     * @return
     */
    public static List<SGCommonProto.ActivityHallColumn.Builder> initActivityDayHallInfoList(){
        List<SGCommonProto.ActivityHallColumn.Builder> list = new CopyOnWriteArrayList<>();
        List<ActivityHallConfig> configList = DataFactory.getInstance(LoadFactory.isTestLoad()).getDataList(DataFactory.ACTIVITY_HALL);
        TwoTuple<Long,Long> twoTuple = getInDayTime();
        configList.forEach((config)->{
            SGCommonProto.ActivityHallColumn.Builder column = com.douqu.game.core.util.time.TimeUtils.testActicityHallColumn(config);
            if (column != null)
                list.add(column);
        });
        return list;
    }

    /**
     * 不同玩家本日 活动大厅显示的状态与参数的不同
     * @param player
     * @param list
     * @return
     */
    public static List<SGCommonProto.ActivityHallColumn.Builder> getActivityDayHallInfoByPlayer(final Player player,List<SGCommonProto.ActivityHallColumn.Builder> list){
        List<SGCommonProto.ActivityHallColumn.Builder> result = new CopyOnWriteArrayList<>();
        if (!list.isEmpty()){
            list.forEach((column)->{
                result.add(com.douqu.game.core.util.time.TimeUtils.getActivityHallColumn(column,player));
            });
        }
        return result;

    }


    public static void main(String[] args) {

//        System.out.println(CoreUtils.formRuleId(132097));
    }
}
